/**
 * Copyright (c) 2006 RiseSoft Co.,Ltd  
 * $Header$
 */
package cn.newtest.bi.collection.groovy;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.risesoft.risebi.collection.model.RangeObj;
import net.risesoft.risebi.collection.model.ReportData;
import net.risesoft.risebi.collection.model.ReportInstance;
import net.risesoft.risebi.collection.model.ReportPeriod;
import net.risesoft.risebi.collection.model.RowObj;
import net.risesoft.risebi.collection.model.SoInstance;
import net.risesoft.risebi.collection.model.Template;
import net.risesoft.risebi.collection.model.User;
import net.risesoft.risebi.collection.service.DataOperationManager;
import net.risesoft.risebi.collection.service.ReportInstanceManager;
import net.risesoft.risebi.collection.service.SoInstanceManager;
import net.risesoft.risebi.collection.service.TemplateManager;
import net.risesoft.risebi.commons.util.ContextUtil;
import net.risesoft.risebi.commons.util.ExceptionUtil;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 *
 *
 * @author <a href="mailto: chenjian@risesoft.net">陈健</a>
 * @version $Revision$
 * 
 */
public class Groovior {
	
	private static Log log = LogFactory.getLog(Groovior.class);
	
	public ReportInstance ri;
	public ReportData rd;
	
	protected Map<String,ReportData> rdMap = new HashMap<String,ReportData>();
	
	public User user;
	
	protected Map<String,String> proAlias = new HashMap<String,String>();
	protected Map<String,String> proAliasReverse = new HashMap<String,String>();
	
	protected Map<String,String> rangeCatalogNameMap;
	protected Map<String,List<String>> rangeSortedCotalogCodeMap;
	
	protected Map localVariables = new HashMap();
	
	public List<Fault> faults = new ArrayList<Fault>();
	
	public void assign(String left,Object right){
		if(right==null)
			return;
		left = left.substring(1);
		
		Map<String,String> indis = rd.getIndis();
		if(indis==null){
			indis = new HashMap<String, String>();
			rd.setIndis(indis);
		}
			
		indis.put(left, right.toString());
	}
	
	public String getBGQ(String bgq) {
		if(ri==null)
			return "";
		
		ReportPeriod reportPeriod = ri.getReportPeriod();
		if(reportPeriod==null)
			return "";
		
		String name = reportPeriod.getName();
		return name;
	}
	
	public String getTBRQ(String tbrq) {
		Calendar c = Calendar.getInstance();
		String year = String.valueOf(c.get(Calendar.YEAR));
		String month = String.valueOf(c.get(Calendar.MONTH)+1);
		String date = String.valueOf(c.get(Calendar.DATE));
		
		String[] tbrqColl = tbrq.split("\\.");
		if(tbrqColl.length<1){
			return year;
		}else{
			String reValue = null;
			for(int i=0;i<tbrqColl.length;i++){
				if(tbrqColl[i].equals("y")||tbrqColl[i].equals("Y")){
					if(reValue==null)
						reValue = year;
				}
				if(tbrqColl[i].equals("m")||tbrqColl[i].equals("M")){
					if(reValue==null)
						reValue = month;
					else
						reValue += "-"+month;
				}
				if(tbrqColl[i].equals("d")||tbrqColl[i].equals("D")){
					if(reValue==null)
						reValue = date;
					else
						reValue += "-"+date;
				}
			}
			
			return reValue;
		}
	}
	
	public String getQYMC() {
		
		return ri.getItem_name();
	}
	
	public String getTBR() {
		return user.getRealName();
	}
	
	public String getZZJGDM() {
//		if(ri!=null){
//			SoInstance si = ri.getSoInstance();
//			if(si!=null){
//				String code = si.getCode();
//				if(code!=null)
//					return code;
//			}
//		}
		
		return "";
	}
	
	public Object getRangeCellValue(String rangeCell){
		String[] rangeCellColl = this.getRangeRowColName(rangeCell);
		
		return this.getRangeCellValue(rangeCellColl);
	}
	
	public Object getRangeCellValue(String[] rangeCellColl){
		Map<String,RangeObj> ranges = null;
		
		int iPos = rangeCellColl[0].indexOf('.');
		if(iPos>-1){
			String rdName = rangeCellColl[0].substring(0,iPos);
			ReportData reportData = rdMap.get(rdName);
			if(reportData==null)
				return 0;
			ranges = reportData.getRanges();
			String rangeName = rangeCellColl[0].substring(iPos+1);
			rangeCellColl[0] = rangeName;
		}else{
			ranges = rd.getRanges();
		}

		if(ranges==null)
			return 0;
		
		RangeObj rangeObj = ranges.get(rangeCellColl[0]);
		if(rangeObj==null)
			return 0;
		
		Map<String,RowObj> rows = rangeObj.getRows();
		if(rows==null)
			return 0;
		
		RowObj rowObj = rows.get(rangeCellColl[1]);
		if(rowObj==null)
			return 0;
		
		Map<String,String> cols = rowObj.getCols();
		if(cols==null)
			return 0;
		
		String value = cols.get(rangeCellColl[2]);
		if(value==null||value.equals("")){
			return 0;
		}
		
		Object reValue = null;
		try {
			Double d = Double.valueOf(value);
			reValue = d;
		} catch (Exception e) {
			reValue = value.trim();
		}
		
		return reValue;
	}
	
	public Object getRangeCellValue(String rangeCell,Map map) throws Exception {
		String rangeName = this.getRangeName(rangeCell);
		map.put("rangeName", rangeName);
		
		String catalogCode = (String) map.get("catalogCode");
		
		List<String> rowList = rangeSortedCotalogCodeMap.get(rangeName);
		if(catalogCode==null){
			catalogCode = rowList.get(0);
			map.put("catalogCode", catalogCode);
		}
		
		String columnName = this.getColumnName(rangeCell);
		String[] rangeCellColl = new String[3];
		rangeCellColl[0] = rangeName;
		rangeCellColl[1] = catalogCode;
		rangeCellColl[2] = columnName;
		
		return this.getRangeCellValue(rangeCellColl);
	}
	
	public void setExitCode(Map<String,List<String>> rangeMap,Map map){
		String rangeName = (String) map.get("rangeName");
		List<String> rowList = rangeMap.get(rangeName);
		String catalogCode = (String) map.get("catalogCode"); 
		for(int i=0;i<rowList.size();i++){
			String catalogCodeTemp = rowList.get(i);
			if(catalogCodeTemp.equals(catalogCode)){
				if(i==rowList.size()-1){
					map.put("exitCode",true);
					return;
				}
				catalogCode = rowList.get(i+1);
				map.put("catalogCode", catalogCode);
				map.put("exitCode",false);
				return;
			}
		}
	}
	
//	rangeCell for example: R[001,b]
	private String getColumnName(String rangeCell){
		int iPos1 = rangeCell.indexOf(',');
		int iPos2 = rangeCell.indexOf(']');
		String columnNameTemp = rangeCell.substring(iPos1+1,iPos2);
		String columnName = proAliasReverse.get(columnNameTemp);
		if(columnName==null){
			return columnNameTemp;
		}else{
			return columnName;
		}
	}
	
//	rangeCell for example: R[001,b]
	private String getRangeName(String rangeCell){
		int iPos = rangeCell.indexOf('[');
		String rangeNameTemp = rangeCell.substring(0, iPos);
		String rangeName = proAliasReverse.get(rangeNameTemp);
		if(rangeName==null){
			return rangeNameTemp;
		}else{
			return rangeName;
		}
	}
	
//	rangeCell for example: R[001,b]/R[i,b] i 是变量
	private String[] getRangeRowColName(String rangeCell){
		String[] rangeCellColl = new String[3];
		int iPos1 = rangeCell.indexOf('[');
		int iPos2 = rangeCell.indexOf(',');
		int iPos3 = rangeCell.indexOf(']');
		rangeCellColl[0] = rangeCell.substring(0, iPos1);
		rangeCellColl[1] = rangeCell.substring(iPos1+1, iPos2);
		rangeCellColl[2] = rangeCell.substring(iPos2+1, iPos3);
		
		String rangeName = proAliasReverse.get(rangeCellColl[0]);
		if(rangeName!=null){
			rangeCellColl[0] = rangeName;
		}
		
		String catalogCodeTemp = (String) localVariables.get(rangeCellColl[1]);
		if(catalogCodeTemp!=null){
			rangeCellColl[1] = catalogCodeTemp;
		}
		
		String columnName = proAliasReverse.get(rangeCellColl[2]);
		if(columnName!=null){
			rangeCellColl[2] = columnName;
		}
		
		return rangeCellColl;
	}
	
	public Object getIndicationValue(String indicationName){
		Map<String,String> indis = rd.getIndis();
		if(indis==null)
			return 0;
		
		String value = indis.get(indicationName.substring(1));
		if(value==null||value.equals("")){
			return 0;
		}
		
		Object reValue = null;
		try {
			Double d = Double.valueOf(value);
			reValue = d;
		} catch (Exception e) {
			reValue = value.trim();
		}
		
		return reValue;
	}
	
	public boolean sure(boolean b,String notice,String cells){
		if(!b){
			addErrors(notice,cells);
		}
		return b;
	}
	
	public Object abs(String cell) {
		Object o = null;
		char charTemp = cell.charAt(0);
		if(charTemp=='&'){
			o = this.getIndicationValue(cell.substring(1));
		}else{
			o = this.getRangeCellValue(cell);
		}
		
		if(o==null||o.equals(""))
			return 0;
		
		try {
			Double d = Double.valueOf(o.toString());
			if(d<0)
				d = 0 - d;
			return d;
		} catch (Exception e) {
//			reValue = value.trim();
		}
		
		return 0;
	}
	
	public Integer len(String cell){
		if(cell==null)
			return 0;
		
		char charTemp = cell.charAt(0);
		if(charTemp=='&'){
			String fullName = cell.substring(1);
			Map<String,String> indis = rd.getIndis();
			String value = indis.get(fullName);
			if(value==null||value.equals("")){
				return 0;
			}
			
			return value.length();
		}else{
			String[] rangeCellColl = this.getRangeRowColName(cell);
			Map<String,RangeObj> ranges = rd.getRanges();
			if(ranges==null)
				return null;
			
			RangeObj rangeObj = ranges.get(rangeCellColl[0]);
			if(rangeObj==null)
				return null;
			
			Map<String,RowObj> rows = rangeObj.getRows();
			if(rows==null)
				return null;
			
			RowObj rowObj = rows.get(rangeCellColl[1]);
			if(rowObj==null)
				return null;
			
			Map<String,String> cols = rowObj.getCols();
			if(cols==null)
				return null;
			
			String value = cols.get(rangeCellColl[2]);
			if(value==null||value.equals("")){
				return null;
			}
			
			return value.length();
		}
	}
	
	public Integer len(String cell,Map map){
		if(cell==null)
			return 0;
		
		char charTemp = cell.charAt(0);
		if(charTemp=='&'){
			String fullName = cell.substring(1);
			Map<String,String> indis = rd.getIndis();
			String value = indis.get(fullName);
			if(value==null||value.equals("")){
				return null;
			}
			
			return value.length();
		}else{
			String rangeName = this.getRangeName(cell);
			map.put("rangeName", rangeName);
			
			String catalogCode = (String) map.get("catalogCode");
			
			List<String> rowList = rangeSortedCotalogCodeMap.get(rangeName);
			if(catalogCode==null){
				catalogCode = rowList.get(0);
				map.put("catalogCode", catalogCode);
			}
			
			String columnName = this.getColumnName(cell);
			String strRangeCell = rangeName + "[" + catalogCode + "," + columnName + "]";
			
			return this.len(strRangeCell);
		}
	}
	
	public boolean notEmpty(String cell) {
		if(cell==null)
			return false;
		
		char charTemp = cell.charAt(0);
		if(charTemp=='&'){
			String fullName = cell.substring(1);
			Map<String,String> indis = rd.getIndis();
			String value = indis.get(fullName);
			if(value==null||value.equals("")){
				return false;
			}
			
			return true;
		}else{
			String[] rangeCellColl = this.getRangeRowColName(cell);
			Map<String,RangeObj> ranges = rd.getRanges();
			if(ranges==null)
				return false;
			
			RangeObj rangeObj = ranges.get(rangeCellColl[0]);
			if(rangeObj==null)
				return false;
			
			Map<String,RowObj> rows = rangeObj.getRows();
			if(rows==null)
				return false;
			
			RowObj rowObj = rows.get(rangeCellColl[1]);
			if(rowObj==null)
				return false;
			
			Map<String,String> cols = rowObj.getCols();
			if(cols==null)
				return false;
			
			String value = cols.get(rangeCellColl[2]);
			if(value==null||value.equals("")){
				return false;
			}
			
			return true;
		}
	}
	
	public boolean notEmpty(String cell,Map map){
		if(cell==null)
			return false;
		
		char charTemp = cell.charAt(0);
		if(charTemp=='&'){
			String fullName = cell.substring(1);
			Map<String,String> indis = rd.getIndis();
			String value = indis.get(fullName);
			if(value==null||value.equals("")){
				return false;
			}
			
			return true;
		}else{
			String rangeName = this.getRangeName(cell);
			map.put("rangeName", rangeName);
			
			String catalogCode = (String) map.get("catalogCode");
			
			List<String> rowList = rangeSortedCotalogCodeMap.get(rangeName);
			if(catalogCode==null){
				catalogCode = rowList.get(0);
				map.put("catalogCode", catalogCode);
			}
			
			String columnName = this.getColumnName(cell);
			String strRangeCell = rangeName + "[" + catalogCode + "," + columnName + "]";
			
			return this.notEmpty(strRangeCell);
		}
	}
	
	public void addErrors(String notice,String cells){
		Fault fault = new Fault();
		fault.setNotice(notice);
		fault.setCells(cells);
		
		if(!faults.contains(fault))
			faults.add(fault);
	}
	
	public List makeInListStatementList(String beginCode,String endCode,int step){
		List list = new ArrayList();
		int iBeginCode = Integer.parseInt(beginCode);
		int iEndCode = Integer.parseInt(endCode);
		int temp = 0;
		int littleCodeLength = beginCode.length();
		if(iBeginCode>iEndCode){
			temp = iBeginCode;
			iBeginCode = iEndCode;
			iEndCode = temp;
			littleCodeLength = endCode.length();
		}
		
		for(int i=iBeginCode;i<=iEndCode;i+=step){
			String finalCode = completeLeadingZero(i, littleCodeLength);
			list.add(finalCode);
		}
		
		return list;
	}
	
	private String completeLeadingZero(int originalCatalogCode,int codeLength) {
		String strTemp = String.valueOf(originalCatalogCode);
		int originalCodeLength = strTemp.length();
		int betweenLength = codeLength - originalCodeLength;
		for(int i=0;i<betweenLength;i++){
			strTemp = '0' + strTemp;
		}
		return strTemp;
	}
	
	public void openRd(String rdName,String templateCode,int offset,boolean lastyear) {
		if(lastyear){
//			去年的报告期
			if(templateCode==null||templateCode.equals(""))
				templateCode = ri.getTemplate().getCode();
			
//			去年的调查对象 soInstanceGuid
			String appGuid = ri.getTemplate().getApplication().getGuid();
			String soCode = ri.getSoInstanceCode(); // ri.getSoInstance().getCode();
			SoInstanceManager soInstanceManager = (SoInstanceManager) ContextUtil.getAc().getBean("soInstanceManager");
			
			SoInstance soInstance = null;
			try {
				soInstance = soInstanceManager.getSoInstanceByAppGuidSoCode(appGuid, soCode);
			} catch (Exception e) {
				log.error("在获取 appGuid："+appGuid+",soCode:"+soCode+"时，发生错误，错误的原因："+ExceptionUtil.transformException(e));
			}
			
			if(soInstance==null){
				return;
			}
			
//			去年的报告期
			ReportPeriod lastYearReportPeriod = ri.getReportPeriod().getLastyear_term();
			if(lastYearReportPeriod==null)
				return;
			
//			获得 所有 templateCode 相同的模板，不包括本期
			TemplateManager templateManager = (TemplateManager) ContextUtil.getAc().getBean("templateManager");
			List<Template> templates = null;
			try {
				templates = templateManager.getTemplatesByCodeExcludeApplication(appGuid,templateCode);
			} catch (Exception e) {
				log.error("在获取 templateCode:"+templateCode+",不是 appGuid:"+appGuid +"的模板列表时发生错误，错误的原因："+ExceptionUtil.transformException(e));
			}
			
			if(templates==null||templates.isEmpty()){
				return;
			}
			
			String soInstanceGuid = soInstance.getGuid();
			String lastYearReportPeriodGuid = lastYearReportPeriod.getGuid();
			
			ReportInstanceManager reportInstanceManager = (ReportInstanceManager) ContextUtil.getAc().getBean("reportInstanceManager");
			ReportInstance lastYearReportInstance = null;
			try {
//				lastYearReportInstance = reportInstanceManager.getRiBySoInstanceReportPeriodTemplates(soInstanceGuid,lastYearReportPeriodGuid,templates);
			} catch (Exception e) {
				log.error("在获得去年同期报表 soInstanceGuid:"+soInstanceGuid+",lastYearReportPeriodGuid:"+lastYearReportPeriodGuid+"时发生错误，错误的原因："+ExceptionUtil.transformException(e));
			}
			
			if(lastYearReportInstance==null)
				return;
			
			DataOperationManager dataOperationManager = (DataOperationManager) ContextUtil.getAc().getBean("dataOperationManager");
			
			ReportData lastYearReportData = null;
			try {
				lastYearReportData = dataOperationManager.getReportData(lastYearReportInstance, lastYearReportInstance.getTemplateGuid());
			} catch (Exception e) {
				log.error("获取 templateGuid:"+lastYearReportInstance.getTemplateGuid()+",lastYearReportPeriod:"+lastYearReportPeriodGuid+",soInstanceGuid:"+soInstanceGuid+" 时发生错误，错误的原因：\r"+ExceptionUtil.transformException(e));
			}
			
			if(lastYearReportData==null)
				return;
			
			rdMap.put(rdName, lastYearReportData);
		}else{
//			表明今年的报告期
			if(templateCode==null||templateCode.equals("")){
//				表明是今年报告期的同一份报表模板
				if(offset>1){
//					目前暂时只提供上期
					return;
				}
				ReportPeriod rp = ri.getReportPeriod();
				ReportPeriod previousReportPeriod = rp.getPrevious_term();
				if(previousReportPeriod==null)
					return;
				
				String templateGuid = ri.getTemplateGuid();
				String previousReportPeriodGuid = previousReportPeriod.getGuid();
				String soInstanceGuid = ri.getSoInstanceGuid(); // ri.getSoInstance().getGuid();
				
				ReportInstanceManager reportInstanceManager = (ReportInstanceManager) ContextUtil.getAc().getBean("reportInstanceManager");
				
				ReportInstance previousReportInstance = null;
				try {
//					previousReportInstance = reportInstanceManager.getReportInstanceByTRSoInstanceGuid(templateGuid,previousReportPeriodGuid,soInstanceGuid);
				} catch (Exception e) {
					log.error("获取 templateGuid:"+templateGuid+",previousReportPeriod:"+previousReportPeriod+",soInstanceGuid:"+soInstanceGuid+" 时发生错误，错误的原因：\r"+ExceptionUtil.transformException(e));
				}
				
				if(previousReportInstance==null)
					return;
				
				DataOperationManager dataOperationManager = (DataOperationManager) ContextUtil.getAc().getBean("dataOperationManager");
				
				ReportData previousReportData = null;
				try {
					previousReportData = dataOperationManager.getReportData(previousReportInstance, templateGuid);
				} catch (Exception e) {
					log.error("获取 templateGuid:"+templateGuid+",previousReportPeriod:"+previousReportPeriod+",soInstanceGuid:"+soInstanceGuid+" 时发生错误，错误的原因：\r"+ExceptionUtil.transformException(e));
				}
				
				if(previousReportData==null)
					return;
				
				rdMap.put(rdName, previousReportData);
			}else{
//				表明是今年报告期的其他报表模板
				String appGuid = ri.getTemplate().getApplication().getGuid();
				TemplateManager templateManager = (TemplateManager) ContextUtil.getAc().getBean("templateManager");
				Template template = null;
				try {
					template = templateManager.getTemplateByApplicationTemplateCode(appGuid, templateCode);
				} catch (Exception e) {
					log.error("获取不到 applicationGuid:"+appGuid+",templateCode:"+templateCode+"对应的模板");
				}
				
				if(template==null)
					return;
				
				String templateGuid = template.getGuid();
				String reportPeriodGuid = ri.getReportPeriodGuid();
				String soInstanceGuid = ri.getSoInstanceGuid(); // ri.getSoInstance().getGuid();
				
				ReportInstanceManager reportInstanceManager = (ReportInstanceManager) ContextUtil.getAc().getBean("reportInstanceManager");
				
				ReportInstance anotherReportInstance = null;
				try {
//					anotherReportInstance = reportInstanceManager.getReportInstanceByTRSoInstanceGuid(templateGuid,reportPeriodGuid,soInstanceGuid);
				} catch (Exception e) {
					log.error("获取 templateGuid:"+templateGuid+",reportPeriodGuid:"+reportPeriodGuid+",soInstanceGuid:"+soInstanceGuid+" 时发生错误，错误的原因：\r"+ExceptionUtil.transformException(e));
				}
				
				if(anotherReportInstance==null)
					return;
				
				DataOperationManager dataOperationManager = (DataOperationManager) ContextUtil.getAc().getBean("dataOperationManager");
				
				ReportData anotherReportData = null;
				try {
					anotherReportData = dataOperationManager.getReportData(anotherReportInstance, templateGuid);
				} catch (Exception e) {
					log.error("获取 templateGuid:"+templateGuid+",previousReportPeriod:"+reportPeriodGuid+",soInstanceGuid:"+soInstanceGuid+" 时发生错误，错误的原因：\r"+ExceptionUtil.transformException(e));
				}
				
				if(anotherReportData==null)
					return;
				
				rdMap.put(rdName, anotherReportData);
			}
		}
	}
}
